import ctypes
import os
import re
import sys
import time

import psutil
from PySide6 import QtWidgets
from PySide6.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, QComboBox, QTextEdit, \
    QPushButton, QMessageBox


class NetCard_Config_Manage(QWidget):
    def __init__(self):
        super(NetCard_Config_Manage, self).__init__()
        self.test_ip = "192.168.100.11"
        self.ip = "192.168.100.124"
        self.subnet = "255.255.255.0"
        self.gateway = "192.168.100.1"

        self.interface_name_list = []  # 存储网络名称的列表
        self.interface_info_list = []  # 存储网络信息的列表
        self.ipconfig = {}             # 存储接口信息的字典
        self.roundRobin_flag = True    # 是否轮询的标志
        self.firstTips_flag = True         # 第一次轮询的结果提示

        # self.get_name_list()
        # self.initset()
        # print(self.ping_test())

    def initset(self):
        self.setWindowTitle('网卡配置修改')
        self.setFixedSize(400, 400)
        self.layout = QGridLayout(self)

        self.label_top = QLabel("网卡选择")

        self.comboBox = QComboBox()
        # self.comboBox.setFixedSize(200, 20)
        self.get_interface_name()
        self.comboBox.addItems(self.interface_name_list)
        self.comboBox.currentIndexChanged.connect(self.combox_index_changed)

        self.content = QTextEdit()
        self.content.setText("网络配置修改")

        self.button_action = QPushButton("确认修改")
        self.button_Adaptive = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self.button_action.setSizePolicy(self.button_Adaptive)
        self.button_action.clicked.connect(self.button_action_clicked)

        self.button_default = QPushButton("恢复自动配置")
        self.button_default.setSizePolicy(self.button_Adaptive)
        self.button_default.clicked.connect(self.button_default_clicked)

        self.layout.addWidget(self.label_top, 0, 0, 1, 1)
        self.layout.addWidget(self.comboBox, 0, 1, 1, 5)
        self.layout.addWidget(self.content, 1, 0, 6, 6)
        self.layout.addWidget(self.button_action, 7, 0, 2, 3)
        self.layout.addWidget(self.button_default, 7, 3, 2, 3)

        # 设置第一条目
        if self.interface_name_list:
            self.combox_index_changed(0)

        self.show()

    def get_interface_name(self):
        self.interface_name_list = []  # 存储网络名称的列表
        self.interface_info_list = []  # 存储网络信息的列表
        interface_name_list = []
        interface_info_list = []
        interfaces = psutil.net_if_addrs()
        interfaces_Info = psutil.net_if_stats()
        # print(interfaces)
        for name, values in interfaces.items():
            family_value = 0
            infomation = ""
            if interfaces_Info[name].isup == True:
                infomation += "连接状态:" + "已连接" + "\n"
            else:
                infomation += "连接状态:" + "已断开" + "\n"

            for value in values:
                if value.family == -1:
                    family_value += 1

                if value.family == 2:
                    family_value += 1

            for value in values:
                if value.family == 23:
                    infomation += "本地链接 IPv6 地址:" + value.address + "\n"

            for value in values:
                if value.family == 2:
                    infomation += "IPv4 地址:" + value.address + "\n"
                    if value.netmask is not None:
                        infomation += "子网掩码:" + value.netmask + "\n"
                    else:
                        infomation += "子网掩码:" + "" + "\n"
                    if value.broadcast is not None:
                        infomation += "默认网关:" + value.broadcast + "\n"
                    else:
                        infomation += "默认网关:" + "" + "\n"

            if family_value >= 2:
                interface_name_list.append(name)
                interface_info_list.append(infomation)

        self.interface_name_list = interface_name_list
        self.interface_info_list = interface_info_list

    def combox_index_changed(self, index):
        self.get_interface_name()
        print(index, len(self.interface_name_list))
        self.content.setText(self.interface_info_list[index])

    def button_action_clicked(self):
        interface_name = self.comboBox.currentText()
        information = ""  # 更新展示消息
        if self.isAdmin() == False:
            QMessageBox.information(self, "提示", "请以管理员身份运行程序", QMessageBox.Yes)
            return
        reply = QMessageBox.information(self, "提示", "是否将' " + interface_name + " ' 修改为DHCP和静态IP共存方式?",
                                        QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            information += """ netsh int ipv4 set interface "{}" dhcpstaticipcoexistence=enabled \n""".format(
                interface_name)
            self.content.setText(information)
            p = os.popen(
                """ netsh int ipv4 set interface "{}" dhcpstaticipcoexistence=enabled""".format(interface_name))
            line = p.read()
            information += line
            self.content.setText(information)

            information += """netsh int ipv4 add address "{}" {} {} \n""".format(interface_name, self.ip, self.subnet)
            self.content.setText(information)
            p = os.popen("""netsh int ipv4 add address "{}" {} {}""".format(interface_name, self.ip, self.subnet))
            line = p.read()
            information += line
            self.content.setText(information)

            QMessageBox.information(self, "提示", "修改成功", QMessageBox.Yes)
            return

    def button_default_clicked(self):
        interface_name = self.comboBox.currentText()
        information = ""  # 更新展示消息
        # if self.isAdmin() == False:
        #     QMessageBox.information(self, "提示", "请以管理员身份运行程序", QMessageBox.Yes)
        #     return
        reply = QMessageBox.information(self, "提示", "是否将' " + interface_name + " ' 修改为DHCP方式?",
                                        QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            information += """ netsh int ipv4 set interface "{}" dhcpstaticipcoexistence=disabled \n""".format(
                interface_name)
            self.content.setText(information)
            p = os.popen(
                """ netsh int ipv4 set interface "{}" dhcpstaticipcoexistence=disabled""".format(interface_name))
            line = p.read()
            information += line
            self.content.setText(information)

            information += """netsh interface ip delete address "{}" addr={} \n""".format(interface_name, self.ip)
            self.content.setText(information)
            p = os.popen("""netsh interface ip delete address "{}" addr={}""".format(interface_name, self.ip))
            line = p.read()
            information += line
            self.content.setText(information)

            QMessageBox.information(self, "提示", "修改成功", QMessageBox.Yes)
            return

    def set_netConfig(self, result):
        index = 0
        for key in result:
            if self.setDHCP_static_ip(key, True):
                if self.add_staticIP(key, self.ip, self.subnet, self.gateway):
                    index += 1
                else:
                    self.setDHCP_static_ip(key, False)
            else:
                pass
        return str(len(result)), str(index)

    def search_dsp_netcard(self):
        result = []
        ip_address_temp = ""
        ip_subnet_temp = ""
        ip_gateway_temp = ""
        for key, value in self.ipconfig.items():
            # print(key)
            if "适配器类型" in value and value["适配器类型"] == "无线局域网适配器":
                # print(value["适配器类型"])
                continue
            if "媒体状态" in value and value["媒体状态"] == "媒体已断开连接":
                # print(value["媒体状态"])
                continue
            if "工作状态" in value and value["工作状态"] == "正在工作":
                # print(value["工作状态"])
                continue
            if "DHCP 已启用" in value and value["DHCP 已启用"] == "是":
                if "IPv4 地址" in value and value["IPv4 地址"] == self.ip:
                    # print(value["IPv4 地址"])
                    continue
                else:
                    # print(1, time.time())
                    if self.setDHCP_static_ip(key, True):
                        if self.add_staticIP(key, self.ip, self.subnet, self.gateway):
                            # print('1-----------')
                            time.sleep(4)
                            # print("2------------")
                            # print(2, time.time())
                            result2 = self.ping_test()
                            # print("result2", result2)
                            if result2:
                                result.append(key)
                            self.delete_staticIP(key, self.ip)
                            self.setDHCP_static_ip(key, False)
                        else:
                            self.setDHCP_static_ip(key, False)
                    else:
                        pass
            else:
                if "IPv4 地址" in value and value["IPv4 地址"] == self.ip:
                    continue
                else:
                    if "IPv4" in value:
                        ip_address_temp = value["IPv4 地址"]
                    if "子网掩码" in value:
                        ip_subnet_temp = value["子网掩码"]
                    if "默认网关" in value:
                        ip_gateway_temp = value["默认网关"]
                    if self.setDHCP_enabled(key, False, self.ip, self.subnet, self.gateway):
                        time.sleep(4)
                        result = self.ping_test()
                        if result:
                            result.append(key)
                        self.setDHCP_enabled(key, False, ip_address_temp, ip_subnet_temp, ip_gateway_temp)
                    else:
                        pass
        return result

    def setDHCP_static_ip(self, interface_name, flag):
        """ 设置是否为DHCP与静态IP共存方式 """
        if flag:
            if not self.isAdmin():
                return False
            p = os.popen(""" netsh int ipv4 set interface "{}" dhcpstaticipcoexistence=enabled""".format(interface_name))
            line = p.read()
            if "确定" in line:
                return True
            else:
                return False
        else:
            if not self.isAdmin():
                return False
            p = os.popen(""" netsh int ipv4 set interface "{}" dhcpstaticipcoexistence=disabled""".format(interface_name))
            line = p.read()
            if "确定" in line:
                return True
            else:
                return False



    def delete_staticIP(self, interface_name, ip_address):
        """ 删除一个静态IP地址 """
        if not self.isAdmin():
            return False
        p = os.popen("""netsh interface ip delete address "{}" addr={}""".format(interface_name, ip_address))
        line = p.read()
        if " " in line:
            return True
        else:
            return False

    def add_staticIP(self, interface_name, ip_address, subnet, gateway):
        """ 添加一个静态IP地址 """
        if not self.isAdmin():
            return False
        p = os.popen("""netsh int ipv4 add address "{}" {} {} {}""".format(interface_name, ip_address, subnet, gateway))
        line = p.read()
        if "对象已存在" in line:
            return False
        elif "\n" == line:
            return True
        else:
            return True

    def setDHCP_enabled(self, interface_name, flag, ip, subnet, gateway):
        """ 设置是否为DHCP动态获取IP地址，如果为否的话给一个静态IP"""
        if flag:
            p = os.popen(""" netsh interface ip set address name={} source=dhcp""".format(interface_name))
            line = p.read()
            if " " in line or "已在此接口上启用 DHCP" in line:
                return True
            else:
                return False
        else:
            p = os.popen(""" netsh int ipv4 set address "{}" static {} {} {}""".format(interface_name, ip, subnet, gateway))
            line = p.read()
            if " " in line:
                return True
            else:
                return False

    def isAdmin(self):
        """ 判断程序是否以管理员身份运行 """
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        except:
            return False

    def ping_test(self):
        # print('3------------')
        p = os.popen("ping " + self.test_ip + " -n 2 -w 20")
        line = p.read()
        # print(line)
        if "请求超时" in line or "无法访问目标主机" in line or "找不到主机" in line or '传输失败' in line:
            return False
        else:
            return True

    def get_ipConfig(self):
        ipconfig = {}
        name_temp = ''
        with os.popen("ipconfig /all") as f:
            for line in f.readlines():
                # print(line.rstrip('\n'))
                if "以太网适配器 " in line:
                    name_temp = line.split("以太网适配器 ")[-1].strip(":\n")
                    ipconfig[name_temp] = {}
                    ipconfig[name_temp]["适配器类型"] = "以太网适配器"
                if "无线局域网适配器 " in line:
                    name_temp = line.split("无线局域网适配器 ")[-1].strip(":\n")
                    ipconfig[name_temp] = {}
                    ipconfig[name_temp]["适配器类型"] = "无线局域网适配器"
                if "媒体状态" in line:
                    ipconfig[name_temp]["媒体状态"] = self.extract_iaid(line)
                if "描述" in line:
                    ipconfig[name_temp]["描述"] = self.extract_iaid(line)
                if "物理地址" in line:
                    ipconfig[name_temp]["物理地址"] = self.extract_iaid(line)
                if "DHCP 已启用" in line:
                    ipconfig[name_temp]["DHCP 已启用"] = self.extract_iaid(line)
                if "自动配置已启用" in line:
                    ipconfig[name_temp]["自动配置已启用"] = self.extract_iaid(line)
                if "本地链接 IPv6 地址" in line:
                    ipconfig[name_temp]["本地链接 IPv6 地址"] = self.extract_iaid(line)
                if "IPv4 地址" in line:
                    ipconfig[name_temp]["IPv4 地址"] = self.extract_iaid(line)
                if "子网掩码" in line:
                    ipconfig[name_temp]["子网掩码"] = self.extract_iaid(line)
                if "获得租约的时间" in line:
                    ipconfig[name_temp]["获得租约的时间"] = self.extract_iaid(line)
                if "租约过期的时间" in line:
                    ipconfig[name_temp]["租约过期的时间"] = self.extract_iaid(line)
                if "默认网关" in line:
                    ipconfig[name_temp]["默认网关"] = self.extract_iaid(line)
                if "DHCP 服务器" in line:
                    ipconfig[name_temp]["DHCP 服务器"] = self.extract_iaid(line)
                if "DHCPv6 IAID" in line:
                    ipconfig[name_temp]["DHCPv6 IAID"] = self.extract_iaid(line)
                if "DHCPv6 客户端 DUID" in line:
                    ipconfig[name_temp]["DHCPv6 客户端 DUID"] = self.extract_iaid(line)
                if "DNS 服务器" in line:
                    ipconfig[name_temp]["DNS 服务器"] = self.extract_iaid(line)
                if "主 WINS 服务器" in line:
                    ipconfig[name_temp]["主 WINS 服务器"] = self.extract_iaid(line)
                if "TCPIP 上的 NetBIOS" in line:
                    ipconfig[name_temp]["TCPIP 上的 NetBIOS"] = self.extract_iaid(line)
        # 获取工作状态
        interface_connect = psutil.net_connections()
        ip_list = []
        for conn in interface_connect:
            if conn.family == 2 and conn.raddr:
                ip_list.append(conn.laddr[0])
        ip_list = list(set(ip_list))

        for key, value in ipconfig.items():
            if "IPv4 地址" in value:
                if value["IPv4 地址"] in ip_list:
                    ipconfig[key]["工作状态"] = '正在工作'
                else:
                    ipconfig[key]["工作状态"] = '未工作'
            else:
                pass
        self.ipconfig = ipconfig
        return ipconfig

    def extract_iaid(self, line):
        match = re.search(r':(.*)', line)
        if not match:
            return None if line.strip() else line
        else:
            return match.group(1).strip().rstrip('(首选)').rstrip('(试验)')

    def get_roundRobin_flag(self):
        """ 获取轮询标志 """
        return self.roundRobin_flag

    def set_roundRobin_flag(self):
        """ 设置轮询标志 """
        self.roundRobin_flag = False

    def get_firstTips_flag(self):
        """ 获取第一次的标志 """
        return self.firstTips_flag

    def set_firstTips_flag(self):
        """ 设置第一次的标志 """
        self.firstTips_flag = False


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWin = NetCard_Config_Manage()
    myWin.show()
    sys.exit(app.exec())
